﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Data;
using System.Net;
using SharePointSearchBench.Library.Logging;

namespace SharePointSearchBench.Library
{
    /// <summary>
    /// A search context used when performing web service searches.
    /// </summary>
    public class ServiceSearchBenchContext : ISearchBenchContext
    {
        Search search;
        QueryService.QueryService serviceClient;
        string queryPacket;

        /// <summary>
        /// Creates a new instance of the search context.
        /// </summary>
        /// <param name="search"></param>
        public ServiceSearchBenchContext(Search search)
        {
            this.search = search;
        }

        /// <summary>
        /// Gets whether or not this context requires that credentials are set.
        /// </summary>
        public bool RequiresCredentials { get { return true; } }


        /// <summary>
        /// Assembles query packet XML for a web service search.
        /// </summary>
        public void PrepareSearch()
        {
            this.serviceClient = ServiceSearchBenchContext.GetService(this.search.Credentials, this.search.ContextUri);
            if (this.search.SearchType == SearchType.Keyword)
            {
                this.queryPacket = this.search.BuildKeywordQueryPacket();
            }
            else
            {
                this.queryPacket = this.search.BuildFullTextQueryPacket();
            }

            this.search.FinalQueryXml = this.queryPacket;
        }

        /// <summary>
        /// Performs the search operation against the Search web service.
        /// </summary>
        /// <returns></returns>
        public DataSet Execute()
        {
            using (IDisposableLogWriter debug = new DisposableDebugLogWriter("Execute"))
            {
                DataSet results = null;
                debug.WriteMessage("Executing service call with query packet (length: " + this.queryPacket.Length.ToString() + ")");
                results = this.serviceClient.QueryEx(this.queryPacket);
                debug.WriteMessage(string.Format("{0} results found.", results.Tables[0].Rows.Count.ToString()));
                return results;
            }
        }

        /// <summary>
        /// Obtains a collection of available search scopes from the Search service.
        /// </summary>
        /// <returns></returns>
        public Collection<SearchScope> GetScopes()
        {
            using (IDisposableLogWriter logger = new DisposableDebugLogWriter())
            {
                QueryService.QueryService client = ServiceSearchBenchContext.GetService(this.search.Credentials, this.search.ContextUri);
                logger.WriteMessage("Got client.");
                client.Credentials = this.search.Credentials;

                NetworkCredential creds = client.Credentials as NetworkCredential;
                logger.WriteMessage("Username: " + creds.UserName);
                logger.WriteMessage("password: " + creds.Password);
                logger.WriteMessage("Domain: " + creds.Domain);

                client.Url = this.search.ContextUri.AbsoluteUri;
                DataSet metadata = client.GetSearchMetadata();
                logger.WriteMessage("Executing - getting scopes.");
                Collection<SearchScope> scopes = SearchScope.GetScopesFromRawDataSet(metadata);
                return scopes;
            }
        }

        /// <summary>
        /// Obtains a collection of available managed properties from the Search service.
        /// </summary>
        /// <returns></returns>
        public Collection<SearchProperty> GetSearchProperties()
        {
            using (IDisposableLogWriter logger = new DisposableDebugLogWriter())
            {
                QueryService.QueryService client = ServiceSearchBenchContext.GetService(this.search.Credentials, this.search.ContextUri);
                logger.WriteMessage("Got client.");
                client.Credentials = this.search.Credentials;
                client.Url = this.search.ContextUri.AbsoluteUri;

                NetworkCredential creds = client.Credentials as NetworkCredential;
                logger.WriteMessage("Username: " + creds.UserName);
                logger.WriteMessage("password: " + creds.Password);
                logger.WriteMessage("Domain: " + creds.Domain);

                
                DataSet metadata = client.GetSearchMetadata();
                logger.WriteMessage("Executing - getting properties.");
                Collection<SearchProperty> properties = SearchProperty.GetPropertiesFromRawDataSet(metadata);
                return properties;
            }
        }

        static QueryService.QueryService GetService(NetworkCredential credentials, Uri serviceUri)
        {
            QueryService.QueryService client = new SharePointSearchBench.Library.QueryService.QueryService();
            client.Url = serviceUri.AbsoluteUri;
            client.Credentials = credentials;
            return client;
        }

    }
}
